package cc.comac.saic.hkhy.jsrj.gj.inttools.gitlab;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.gitlab4j.api.CommitsApi;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.GroupApi;
import org.gitlab4j.api.ProjectApi;
import org.gitlab4j.api.RepositoryFileApi;
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.models.CommitAction;
import org.gitlab4j.api.models.CommitPayload;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.RepositoryFile;
import org.gitlab4j.api.models.Visibility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import cc.comac.saic.hkhy.jsrj.gj.inttools.constant.FileType;
import jakarta.servlet.http.Part;

/**
 * @Author: Nemo
 * @ClassName: GitlabClient
 * @Date: 2025/7/2 20:31
 * @Description: 介是嘛？
 **/
@Service
public class VersionManegeClient {
    @Autowired
    private GitLabApi gitLabApi;

    public void initProject(String projKey, String projName) throws GitLabApiException {
        GroupApi groupApi = gitLabApi.getGroupApi();
        ProjectApi projectApi = gitLabApi.getProjectApi();

        // fixme 清理现有组和项目(慎用！正式版请勿使用)
        // cleanAll();

        // 创建新组
        Group group = new Group().withName(projKey)
            .withPath(projKey)
            .withDescription(projName)
            .withVisibility(Visibility.PUBLIC);
        group = groupApi.addGroup(group);


        // 创建新项目
        for (FileType value : FileType.values()) {
            String code = value.getCode();
            Project project = new Project()
                .withName(code)
                .withPath(code)
                .withVisibility(Visibility.PUBLIC)
                .withNamespaceId(group.getId());
            projectApi.createProject(project);
        }
    }


    public String uploadFiles(String projKey, FileType fileType, Collection<Part> fileParts) throws GitLabApiException {
        RepositoryFileApi repositoryFileApi = gitLabApi.getRepositoryFileApi();
        CommitsApi commitsApi = gitLabApi.getCommitsApi();

        String projectPath = projKey + "/" + fileType.getCode();

        List<CommitAction> commitActions = fileParts.stream()
            .filter(part -> StringUtils.hasText(part.getSubmittedFileName()))
            .map(part -> {
                try {
                    String originalFilePath = part.getSubmittedFileName();
                    CommitAction commitAction;
                    CommitAction.Action action = null;
                    try {
                        repositoryFileApi.getFile(projectPath, originalFilePath, "master");
                        action = CommitAction.Action.UPDATE;
                    } catch (Exception e) {
                        action = CommitAction.Action.CREATE;
                    } finally {
                        commitAction = GitlabFileUtils.newCommitAction(part)
                            .withAction(action);
                    }
                    return commitAction;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }).collect(Collectors.toList());

        CommitPayload commitPayload = new CommitPayload()
            .withBranch("master")
            .withCommitMessage("auto commit at: " + new Date())
            .withActions(commitActions);

        Commit commit = commitsApi.createCommit(projectPath, commitPayload);

        return commit.getId();
    }

    public byte[] getFileBytes(String projKey, FileType fileType, String filePath, String versionHash) throws GitLabApiException {
        RepositoryFileApi repositoryFileApi = gitLabApi.getRepositoryFileApi();
        String projectPath = projKey + "/" + fileType.getCode();
        RepositoryFile repositoryFile = repositoryFileApi.getFile(projectPath, filePath, Objects.isNull(versionHash) ? "master" : versionHash);
        return repositoryFile.getDecodedContentAsBytes();
    }

    public void cleanAll() throws GitLabApiException {
        GroupApi groupApi = gitLabApi.getGroupApi();
        ProjectApi projectApi = gitLabApi.getProjectApi();
        groupApi.getGroups().forEach(group -> {
            try {
                groupApi.deleteGroup(group.getId());
            } catch (GitLabApiException ignored) {
            }
        });

        projectApi.getProjects().forEach(project -> {
            try {
                projectApi.deleteProject(project.getId());
            } catch (GitLabApiException ignored) {
            }
        });
    }
}
